package top.yxqin.easymine.eventProcessor;


import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.ExperienceOrb;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.util.Vector;
import top.yxqin.easymine.PlayerData.PlayerData;
import top.yxqin.easymine.PlayerData.PlayerList;
import top.yxqin.easymine.unit.Configs;


import java.awt.*;
import java.util.ArrayList;
import java.util.List;

//连锁挖矿
public class OnBlockBreak implements Listener
{
    @EventHandler
    public void handle(BlockBreakEvent e)
    {
        Player player=e.getPlayer();
        PlayerData pd= PlayerList.getPlayerData(player.getName());
        ItemStack tool=player.getInventory().getItemInMainHand();
        Block block=e.getBlock();

        //超级挖掘
        if(Configs.enableSuperDig&& pd.isCanSuperDig())
        if(superDig(tool,block,player.getLocation().getDirection())!=0)
            return;
        //连锁挖矿
        if(Configs.enableVeinMine&&pd.isCanVeinMine())
        {
            int cnt=veinMine(tool,block);
            if(e.getExpToDrop()>0&&cnt>0)
                ((ExperienceOrb)  player.getWorld().spawnEntity(block.getLocation(), EntityType.EXPERIENCE_ORB)).setExperience(cnt*e.getExpToDrop());
        }
    }


    // 连锁破坏
    private int superDig(ItemStack tool, Block block,Vector v)
    {
        int cnt=0;
        if(canSuperDig(tool,block))
        {
            Damageable damageable = (Damageable) tool.getItemMeta();
            int maxDurability= tool.getType().getMaxDurability();
            int nowDurability=damageable.getDamage();
            double leve=  1.0/(tool.getEnchantmentLevel(Enchantment.DURABILITY)+1);//耐久附魔等级
            Material type=block.getType();
            Vector face = getFace(v);
            Vector v1,v2;//遍历方向

            if(face.getX()!=0)
            {
                v1=new Vector(0,1,0);
                v2=new Vector(0,0,1);
            }
            else if(face.getY()!=0)
            {
                v1=new Vector(1,0,0);
                v2=new Vector(0,0,1);
            }
            else
            {
                v1=new Vector(1,0,0);
                v2=new Vector(0,1,0);
            }

            Location  root= block.getLocation().add(v1.clone().add(v2).multiply(Configs.SMaxDepth/2));
            int d=0;
            mainWhile:
            while(d<3)
            {
                int n=0;
                for(int i=0;i<Configs.SMaxDepth;++i)
                {
                    Vector  vi =v1.clone().multiply(-i);
                    for(int j=0;j<Configs.SMaxDepth;++j)
                    {
                        Vector  vj= v2.clone().multiply(-j);
                        Location cur=root.clone().add(vj.add(vi));
                        if(cur.getBlock().getType()==type)
                        {
                            cur.getBlock().breakNaturally(tool);
                            ++n;
                            //处理耐久度
                            if(Math.random()<leve)
                                ++nowDurability;
                            if(maxDurability-nowDurability<=1)//耐久度 小于等于1 不再连锁
                                break mainWhile;
                        }
                    }
                }
                if(n==0)
                    break;
                root.add(face);
                cnt+=n;
                ++d;
            }
            damageable.setDamage(nowDurability);
            tool.setItemMeta(damageable);
        }
        return cnt;
    }
    //获取玩家朝向
    private Vector getFace(Vector v)
    {
        double x=Math.abs(v.getX());
        double y=Math.abs(v.getY());
        double z=Math.abs(v.getZ());
        if(x>=y&&x>=z)//x最大
            return new Vector(v.getX()/x,0,0);
        else if(z>=y&&z>=x)
            return new Vector(0,0,v.getZ()/z);
        else
            return new Vector(0,v.getY()/y,0);
    }
    private boolean canSuperDig(ItemStack tool, Block block)
    {
        return Configs.SuperDIG_TOOL.contains(tool.getType().toString())&&Configs.SuperDIG_BLOCK.contains(block.getType().toString());
    }

    //连锁挖矿
    private int veinMine(ItemStack tool, Block block)
    {
        if(canVeinMine(tool,block))
        {
            return linkMine(block,block.getLocation(),tool);
        }
        return 0;
    }
    //检查工具是否可以连锁挖矿
    private  boolean canVeinMine(ItemStack tool, Block block)
    {
        Damageable damageable = (Damageable) tool.getItemMeta();
        Material toolType=tool.getType();
        Material blockType=block.getType();
        //存在耐久 且耐久剩余大于1
        if(damageable!=null&&block.getType()!=Material.AIR&&toolType.getMaxDurability()-damageable.getDamage()>1)
        {
            if(Configs.Pickaxe_SET.contains(toolType.toString()))//稿子
                return Configs.Pickaxe_Block.contains(blockType.toString());
            else if(Configs.AXE_SET.contains(toolType.toString())) //斧子
                return Configs.AXE_BLOCK.contains(blockType.toString());
            else if(Configs.SHOVEL_SET.contains(toolType.toString()))
                return Configs.SHOVEL_BLOCK.contains(blockType.toString());
            else
                return false;
        }
        return false;
    }
    //BFS 连锁挖矿
    private int linkMine(Block block, Location root, ItemStack tool)
    {
        //类型
        Material type=block.getType();
        //耐久度
        Damageable damageable = (Damageable) tool.getItemMeta();
        int maxDurability= tool.getType().getMaxDurability();
        int nowDurability=damageable.getDamage();
        double leve=  1.0/(tool.getEnchantmentLevel(Enchantment.DURABILITY)+1);//耐久附魔等级
        //BFS 搜索
        int cnt=0;//连锁数量
        ArrayList<Location> queue = new ArrayList<>();//队列
        queue.add(root);
        while(cnt<Configs.MaxDepth&& !queue.isEmpty())
        {
            Location current = queue.get(0);
            if(current.getBlock().getType()==type)
            {
                current.getBlock().breakNaturally(tool);
                //block.getWorld().spawnEntity(current.clone(), EntityType.CAT);
//                System.out.println("xp:"+xp);
//                ((ExperienceOrb)  block.getWorld().spawnEntity(current.clone(), EntityType.EXPERIENCE_ORB)).setExperience(xp);
                //处理耐久度
                if(Math.random()<leve)
                    ++nowDurability;
                if(maxDurability-nowDurability<=1)//耐久度 小于等于1 不再连锁
                    break;
                //搜索当前方块周围的六个方块
                ArrayList<Location> nearbys = new ArrayList<>();
                nearbys.add(current.clone().add(1, 0, 0));
                nearbys.add(current.clone().add(-1, 0, 0));
                nearbys.add(current.clone().add(0, 1, 0));
                nearbys.add(current.clone().add(0, -1, 0));
                nearbys.add(current.clone().add(0, 0, 1));
                nearbys.add(current.clone().add(0, 0, -1));
                for(Location nearby : nearbys)
                {
                    //如果是同种方块
                    if (nearby.getBlock().getType() == type)
                        queue.add(nearby);
                }
                ++cnt;
            }
            queue.remove(0);
        }
        damageable.setDamage(nowDurability);
        tool.setItemMeta(damageable);
        return cnt;
    }
}
